#pragma once
#include"mylog.hpp"
#include"Addr.hpp"
#include"common.hpp"
#include"ClientData.hpp"
#include"mypthread.hpp"
using namespace my_log;
using namespace my_pthread;
using func_t =std::function<std::string(std::string& en,Addr& cli)>;
int defaultsockfd=-1;
class tcpserver:public nocopy
{
public:
    tcpserver(uint16_t port,func_t t)
    :_port(port),_t(t),_sockfd(defaultsockfd),_isrunning(false)
    {}
    void Init()
    {
        //首先创建异端
        _sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(_sockfd==-1)
        {
            //创建异端失败
            LOG(LogLevel::FATAL)<<"异端创建失败!";
            exit(Sock::sockerr);
        }
        LOG(LogLevel::DEBUG)<<"异端创建成功,fd:"<<_sockfd;
        //建立绑定
        Addr peer(_port);
        int n=bind(_sockfd,(struct sockaddr*)peer.pSockaddr(),peer.Socklen());
        if(n==-1)
        {
            //绑定失败
            LOG(LogLevel::FATAL)<<"异端绑定失败!";
            exit(Sock::binderr);
        }
        LOG(LogLevel::DEBUG)<<"异端绑定成功,fd="<<_sockfd;
        //设置为listen状态
        int lis=listen(_sockfd,8);
        if(lis==-1)
        {
            LOG(LogLevel::FATAL)<<"监听状态设置失败!";
            exit(Sock::listenerr);
        }
        LOG(LogLevel::DEBUG)<<"监听状态设置成功,fd="<<_sockfd;
    }
    class ClientData
{
public:
    ClientData(int sockfd,Addr cli,tcpserver* tcp)
    :_sockfd(sockfd),_cli(cli),_tcp(tcp)
    {}
    ~ClientData()
    {}
    int _sockfd;
    Addr _cli;
    tcpserver* _tcp;
};
    void Service(int sockfd,Addr& client)
    {
        std::cout<<"进入service";   
        char buffer[1024];
        while(true)
        {
            ssize_t n=read(sockfd,buffer,sizeof(buffer)-1);
            if(n>0)
            {
                //消息接收成功
                buffer[n]=0;//设置为字符串风格,此时的buffer储存的是英文
                //cout<<"this is buffer:"<<buffer;
                //LOG(LogLevel::DEBUG)<<client.GetAddr()<<"asks@"<<buffer;
                //echo
                std::string en=buffer;
                std::string buf=_t(en,client);
                std::string message="server echos@"+buf+'\n';
                int w=write(sockfd,message.c_str(),message.size());
                // //消息接收成功
                // buffer[n]=0;//设置为字符串风格
                // //cout<<"this is buffer:"<<buffer;
                // LOG(LogLevel::DEBUG)<<client.GetAddr()<<"says@"<<buffer;
                // //echo
                // std::string buf=buffer;
                // std::string message="server echos@"+buf+'\n';
                // int w=write(sockfd,message.c_str(),message.size());
                
            }
            else if(n==0)
            {
                //客户关闭连接,读取到文件结尾
                LOG(LogLevel::DEBUG)<<client.GetAddr()<<"退出...";
                close(sockfd);
                break;
            }
            else
            {
                LOG(LogLevel::FATAL)<<client.GetAddr()<<"异常!";
                close(sockfd);
                break;
            }
        }
    }
    static void* Routine(void* args)
    {
        //先把自己分离
        pthread_detach(pthread_self());
        ClientData* cd=static_cast<ClientData*>(args);
        cd->_tcp->Service(cd->_sockfd,cd->_cli);
        delete cd;
        return nullptr;
    }
    void Start()
    {
        _isrunning=true;
        while(_isrunning)
        {
            //多线程版本
            struct sockaddr_in cli;
            cli.sin_family=AF_INET;
            socklen_t len=sizeof(cli);
            int sockfd=accept(_sockfd,(struct sockaddr*)&(cli),&len);
            if(sockfd<0)
            {
                LOG(LogLevel::FATAL)<<"accpet失败!";
                continue;
            }
            Addr client(cli);
            LOG(LogLevel::DEBUG)<<client.GetAddr()<<"用户上线!";
            ClientData cd(sockfd,client,this);
            //创建线程
            // pthread_t tid;
            // pthread_create(&tid,nullptr,Routine,&cd);
            mypthread<ClientData> p([](ClientData cd)->void{
                pthread_detach(pthread_self());
                cd._tcp->Service(cd._sockfd,cd._cli);
            },cd);
            p.start();
            // struct sockaddr_in cli;
            // cli.sin_family=AF_INET;
            // socklen_t len=sizeof(cli);
            // int sockfd=accept(_sockfd,(struct sockaddr*)&(cli),&len);
            // if(sockfd<0)
            // {
            //     LOG(LogLevel::FATAL)<<"accpet失败!";
            //     continue;
            // }
            // Addr client(cli);
            // LOG(LogLevel::DEBUG)<<client.GetAddr()<<"用户上线!";
            // pid_t pid=fork();
            // if(pid<0)
            // {
            //     LOG(LogLevel::FATAL)<<"进程创建失败!";
            //     continue;
            // }
            // else if(pid==0)
            // {
            //     //子进程执行services
            //     if(fork()>0)
            //     {
            //         //子进程退出
            //         exit(Sock::OK);
            //     }
            //     //孙子进程执行service函数，之后变为孤儿进程被系统回收
            //     Service(sockfd,client);
            // }
            // else
            // {
            //     //父进程回收子进程
            //     pid_t p=waitpid(pid,nullptr,0);
            //     (void)p;
            // }
            //单进程版本
            // struct sockaddr_in cli;
            // cli.sin_family=AF_INET;
            // socklen_t len=sizeof(cli);
            // int sockfd=accept(_sockfd,(struct sockaddr*)&(cli),&len);
            // if(sockfd<0)
            // {
            //     LOG(LogLevel::FATAL)<<"accpet失败!";
            //     continue;
            // }
            // Addr client(cli);
            // LOG(LogLevel::DEBUG)<<client.GetAddr()<<"用户上线!";
            // Service(sockfd,client);
        }
        _isrunning=false;
    }
    ~tcpserver()
    {}
private:
    uint16_t _port;
    int _sockfd;
    func_t _t;
    bool _isrunning;
};